package kuzmenkov.oip.service.impl;

import kuzmenkov.oip.adapters.ImageProcessingAdapter;
import kuzmenkov.oip.common.FileTool;
import kuzmenkov.oip.common.I18nTool;
import kuzmenkov.oip.model.Image;
import kuzmenkov.oip.model.Module;
import kuzmenkov.oip.model.Parameter;
import kuzmenkov.oip.service.ImageProcessingService;
import kuzmenkov.oip.service.ModuleChoosingService;

import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpSession;
import java.util.*;
import java.util.logging.Logger;

/**
 * @see kuzmenkov.oip.service.ImageProcessingService
 *      User: Kuzmenkov
 *      Date: 08.03.2009
 *      Time: 13:35:54
 */
public class ImageProcessingServiceImpl implements ImageProcessingService {

    {
        //needs to load the class FileTool
        FileTool ftool = FileTool.getInstance();
    }

    private static final Logger log = Logger.getLogger(ImageProcessingServiceImpl.class.getName());


    private ModuleChoosingService moduleChoosingService = null;
    private I18nTool i18nTool;
    private String sessionId = null;


    public void setI18nTool(I18nTool i18nTool) {
        this.i18nTool = i18nTool;
    }

    public ImageProcessingServiceImpl() {
        initSessionId();
    }

    private void initSessionId() {
        FacesContext context = FacesContext.getCurrentInstance();
        ExternalContext extCont = context.getExternalContext();
        HttpSession session = (HttpSession) extCont.getSession(true);
        sessionId = session.getId();

//        tempDir = FileTool.getInstance().getCommonTempDir() + sessionId + File.separator;
    }

    public void setModuleChoosingService(ModuleChoosingService moduleChoosingService) {
        this.moduleChoosingService = moduleChoosingService;
    }

    public Locale getLocale() throws Exception {
        Locale loc = null;
        try {
            loc = i18nTool.getLocale();
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception(i18nTool.getMessage("ImageProcessingServiceImpl.gettingLocale"));
        }
        return loc;
    }

    @Override
    public String getResult(String input) {
        return "Welcome " + input + "!";
    }

    @Override
    public List getParameters() throws Exception {
        List ps = null;
        try {
            List<Parameter> params = moduleChoosingService.getCurrentModule().getParameters();
            ps = packParams(params);
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception(i18nTool.getMessage("ImageProcessingImpl.gettingParameters"));
        }
        return ps;
    }

    @Override
    public List getImages() throws Exception {
        List<Map<String, Object>> ims = null;
        try {
            Set images = moduleChoosingService.getCurrentModule().getImages();
            ims = packImages(images);
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception(i18nTool.getMessage("ImageProcessingServiceImpl.gettingImages"));
        }
        return ims;
    }

    @Override
    public Object[] process(Object[] params) throws Exception {
        try {
            Module module = moduleChoosingService.getCurrentModule();
            if (module != null) {
                String strAdapter = module.getAdapter();

                Class adapterClass = Class.forName(strAdapter);
                Object obj = adapterClass.newInstance();
                ImageProcessingAdapter adapter = (ImageProcessingAdapter) obj;
                adapter.setSessionId(getSessionId());
                //adapter.setModule(module);
                return adapter.process(params);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception(i18nTool.getMessage("ImageProcessingServiceImpl.processing"));
        }


        return null;
    }

    /**
     * Packs imges into a map for sending to a client
     *
     * @param images
     * @return the map of the images
     */
    private List<Map<String, Object>> packImages(Set<Image> images) {
        List<Map<String, Object>> ims = new ArrayList<Map<String, Object>>();
        for (Image image : images) {
            Map<String, Object> im = packImage(image);
            ims.add(im);
        }
        return ims;
    }

    private Map<String, Object> packImage(Image image) {
        String filePath = image.getFilePath();

        Map<String, Object> im = new HashMap<String, Object>();
        im.put(IMAGE_FILE_PATH, filePath);
        return im;
    }

    /**
     * Packs module parametes into map for sending to a client
     *
     * @param params
     * @return the map of the parameters
     * @throws Exception
     */
    private List<Map<String, Object>> packParams(List<Parameter> params) throws Exception {

        List<Map<String, Object>> ps = new ArrayList<Map<String, Object>>();

        for (Parameter param : params) {
            Map<String, Object> p = packParam(param);
            ps.add(p);
        }
        return ps;

    }

    private Map<String, Object> packParam(Parameter p) throws Exception {
        if (p==null) {
            throw new IllegalArgumentException("Parameter is null");
        }

        String name = i18nTool.internationalizeMethod(p, "getName");
        Boolean isResult = p.getIsResult();
        String description = i18nTool.internationalizeMethod(p, "getDescription");
        String type = p.getType();
        String defaultValue = p.getDefaultValue();
        Integer position = p.getPosition();


        Map<String, Object> map = new HashMap<String, Object>();
        map.put(PARAM_NAME, name);
        map.put(PARAM_IS_RESULT, isResult);
        map.put(PARAM_DESCRIPTION, description);
        map.put(PARAM_TYPE, type);
        map.put(PARAM_DEFAULT_VALUE, defaultValue);
        map.put(PARAM_POSITION, position);

        return map;
    }

    public String getModuleName() throws Exception {
        return moduleChoosingService.getModuleName();
    }

    public String getModuleProducerName() throws Exception {
        return moduleChoosingService.getModuleProducerName();
    }

    public int getPanelWidth() throws Exception {
        try {
            Module m = moduleChoosingService.getCurrentModule();

            if (m != null && m.getPanelWidth() != null)
                return m.getPanelWidth();
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception(i18nTool.getMessage("ImageProcessingServiceImpl.gettingPanelWidth"));
        }
        return 750;
    }

    public int getPanelHeight() throws Exception {
        try {
            Module m = moduleChoosingService.getCurrentModule();
            if (m != null && m.getPanelHeight() != null)
                return m.getPanelHeight();
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception(i18nTool.getMessage(
                    i18nTool.getMessage("ImageProcessingServiceImpl.gettingPanelHeight")));
        }
        return 500;
    }


    public List<ParameterItem> getParameterItems() throws Exception {
        try {
            Module m = moduleChoosingService.getCurrentModule();
            if (m != null) {
                List<Parameter> parameters = m.getParameters();
                List<ParameterItem> paramItems = new ArrayList<ParameterItem>(parameters.size());
                for (Parameter parameter : parameters) {
                    String name = i18nTool.internationalizeMethod(parameter, "getName");
                    String desc = i18nTool.internationalizeMethod(parameter, "getDescription");
                    String defVal = parameter.getDefaultValue();
                    boolean isResult = parameter.getIsResult();

                    ParameterItem item = new ParameterItem(name, desc, defVal, isResult);
                    paramItems.add(item);
                }
                return paramItems;
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception(i18nTool.getMessage("ImageProcessingServiceImpl.gettingParameterItems"));
        }
        return null;
    }

    public String getModuleAdapterClass() throws Exception {
        try {
            Module currMod = moduleChoosingService.getCurrentModule();
            return currMod.getAdapter();
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception(i18nTool.getMessage("ImageProcessingServiceImpl.gettingAdapterClass"));
        }

    }


    /**
     * A path ends with a file separator.
     *
     * @return the path to the temp directory of the current session
     */
    public String getSessionId() {
        return sessionId;
    }

}
